package com.zbkj.crmeb.store.service.impl;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.constants.Constants;
import com.constants.WeChatConstants;
import com.crmeb.core.exception.CrmebException;
import com.crmeb.core.utils.RedisUtil;
import com.utils.CrmebUtil;
import com.utils.DateUtil;
import com.utils.vo.dateLimitUtilVo;
import com.zbkj.crmeb.chant.model.ChannelMerchant;
import com.zbkj.crmeb.chant.service.IChannelMerchantService;
import com.zbkj.crmeb.statistics.response.HomeRateResponse;
import com.zbkj.crmeb.statistics.service.HomeService;
import com.zbkj.crmeb.statistics.service.impl.HomeServiceImpl;
import com.zbkj.crmeb.store.dao.StoreOrderDao;
import com.zbkj.crmeb.store.model.*;
import com.zbkj.crmeb.store.response.DataLiveResponse;
import com.zbkj.crmeb.store.response.DataLiveSingleResponse;
import com.zbkj.crmeb.store.response.GoodsBoardResponse;
import com.zbkj.crmeb.store.service.*;
import com.zbkj.crmeb.system.service.SystemConfigService;
import com.zbkj.crmeb.user.model.User;
import com.zbkj.crmeb.user.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
@Slf4j
public class DataLiveServiceImpl implements DataLiveService {

    @Autowired
    private StoreOrderInfoService storeOrderInfoService;
    @Resource
    private StoreOrderDao storeOrderDao;
    @Autowired
    private StoreOrderStatusService storeOrderStatusService;
    @Autowired
    private UserService userService;
    @Autowired
    private HomeService homeService;
    @Autowired
    private IChannelMerchantService channelMerchantService;
    @Autowired
    private SystemConfigService systemConfigService;
    @Autowired
    private HomeServiceImpl homeServiceImpl;
    @Autowired
    private StoreSaleAnalysisService saleAnalysisService;
    @Autowired
    private StoreProductDescriptionService descriptionService;
    @Autowired
    private StoreProductService productService;
    @Autowired
    private RedisUtil redisUtil;
    @Value("${server.wechatProgramToken}")
    private Boolean programTokenFlag;

    /**
     * @param merIds
     * @Description: 获取实时信息
     * @Return: com.zbkj.crmeb.store.response.DataLiveResponse
     * @Author: wangzh
     * @Date: 2022/10/14 11:41
     */
    @Override
    public DataLiveResponse getLiveData(List<Integer> merIds) {
        //实时信息
        DataLiveResponse liveResponse = new DataLiveResponse();

        //时间区间
        List<String> dateList = getListDate(DateUtil.initDateByDay(), 2);

        //支付金额
        DataLiveSingleResponse payMoney = getLivePayMoney(dateList, merIds);
        liveResponse.setPayMoney(payMoney);

        //支付订单数
        DataLiveSingleResponse payOrder = getLivePayOrder(dateList, merIds);
        liveResponse.setPayOrder(payOrder);

        //支付人数
        DataLiveSingleResponse payNum = getLivePayNum(dateList, merIds);
        liveResponse.setPayNum(payNum);

        //客单价
        DataLiveSingleResponse customerUnitPrice = getCustomerUnitPrice(payMoney, payOrder);
        liveResponse.setCustomerUnitPrice(customerUnitPrice);

        //退款金额
        DataLiveSingleResponse refundPrice = getRefundPrice(dateList, merIds);
        liveResponse.setRefundPrice(refundPrice);

        //新增会员数
        DataLiveSingleResponse VIPNum = getVIPNum(dateList, merIds);
        liveResponse.setVIPNum(VIPNum);

        //浏览量
        HomeRateResponse views = homeService.views(merIds);
        DataLiveSingleResponse browseNum = new DataLiveSingleResponse();
        browseNum.setTodayCount(views.getTodayCount())
                .setYesterdayCount(views.getCount());
        liveResponse.setBrowseNum(browseNum);

        return liveResponse;
    }

    /**
     * @param dateLimit
     * @param merIds
     * @Description: 获取整体面板信息
     * @Return: com.zbkj.crmeb.store.response.DataLiveResponse
     * @Author: wangzh
     * @Date: 2022/10/16 18:53
     */
    @Override
    public DataLiveResponse getWholeData(dateLimitUtilVo dateLimit, List<Integer> merIds) {
        //加1算上当前月
        int interval = (int) (LocalDate.parse(dateLimit.getStartTime()).until(LocalDate.parse(dateLimit.getEndTime()), ChronoUnit.MONTHS) + 1);
        if (interval > 3) {
            throw new CrmebException("月份超出限制，最大选取三个月");
        }
        //整体看板
        DataLiveResponse wholeResponse = new DataLiveResponse();

        LocalDate localDate = LocalDate.parse(dateLimit.getStartTime());
        LocalDate localDate1 = LocalDate.parse(dateLimit.getEndTime());
        //相差天数 包含最后一天
        int len = (int) localDate.until(localDate1, ChronoUnit.DAYS) + 1;
        int intervalDay;
        if (len % 15 < 7) {
            intervalDay = len / 15;
        } else {
            intervalDay = len / 15 + 1;
        }
        //时间列表
        List<String> listDateMonth = DateUtil.getListDateMonth(dateLimit, 15);
        //计算上期的开始与结束时间
        String previousPeriodStartTime = LocalDate.parse(listDateMonth.get(0)).minusMonths(interval).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_START));
        String previousPeriodEndTime = LocalDate.parse(listDateMonth.get(listDateMonth.size() - 1)).minusMonths(interval).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_END));
        dateLimitUtilVo previousDateLimit = new dateLimitUtilVo(previousPeriodStartTime, previousPeriodEndTime);
        //支付金额
        DataLiveSingleResponse wholePayMoney = getWholePayMoney(listDateMonth, merIds, previousDateLimit, intervalDay);
        wholeResponse.setPayMoney(wholePayMoney);

        //支付订单数
        DataLiveSingleResponse wholePayOrder = getWholePayOrder(listDateMonth, merIds, previousDateLimit, intervalDay);
        wholeResponse.setPayOrder(wholePayOrder);

        //支付人数
        DataLiveSingleResponse wholePayNum = getWholePayNum(listDateMonth, merIds, previousDateLimit, intervalDay);
        wholeResponse.setPayNum(wholePayNum);

        //客单价
        DataLiveSingleResponse wholeCustomerUnitPrice = getWholeCustomerUnitPrice(wholePayMoney, wholePayOrder);
        wholeResponse.setCustomerUnitPrice(wholeCustomerUnitPrice);

        //退款金额
        DataLiveSingleResponse wholeRefundPrice = getWholeRefundPrice(listDateMonth, merIds, previousDateLimit, intervalDay);
        wholeResponse.setRefundPrice(wholeRefundPrice);

        //新增会员数
        DataLiveSingleResponse wholeVIPNum = getWholeVIPNum(listDateMonth, merIds, previousDateLimit, intervalDay);
        wholeResponse.setVIPNum(wholeVIPNum);

        return wholeResponse;
    }

    /**
     * 功能描述: 流量看板，用户访问量统计数据
     *
     * @Param: [merIds]
     * @Return: com.zbkj.crmeb.store.response.DataLiveSingleResponse
     * @Author: wangzh
     * @Date: 2022/10/17 13:38
     */
    @Override
    public DataLiveSingleResponse getFlowUserViewsData(List<Integer> merIds) {
        DataLiveSingleResponse flow = new DataLiveSingleResponse();
        Map<Object, Object> flowDataMap = new LinkedHashMap<>();
        //当前时间
        LocalDate nowDay = LocalDate.now();
        //前一个月的开始时间
        LocalDate startDay = nowDay.minusMonths(1).minusDays(1);

        HomeRateResponse views = homeService.views(merIds);
        //昨天与前天的浏览量
        flow.setTodayCount(views.getTodayCount())
                .setYesterdayCount(views.getCount())
                .setDayRate(views.getDayRate());

        if (!programTokenFlag) {
            while (startDay.isBefore(nowDay)){
                flowDataMap.put(startDay.format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_MONTH_DATE)), 0);
                startDay = startDay.plusDays(1);
            }
            flow.setMonthCount(0)
                    .setMonthRate(BigDecimal.ZERO + "%")
                    .setLineChart(flowDataMap);
            return flow;
        }
        List<ChannelMerchant> channelMerchants = channelMerchantService.list(Wrappers.lambdaQuery(ChannelMerchant.class).in(CollectionUtils.isNotEmpty(merIds), ChannelMerchant::getId, merIds));
        int month = 0;
        for (ChannelMerchant channelMerchant : channelMerchants) {
            log.info("-----------获取小程序访问量,商户id:{}-----------", channelMerchant.getId());
            try {
                //反射获取私有方法
                Method getAccessToken = BeanUtils.findDeclaredMethod(homeServiceImpl.getClass(), "getAccessToken", String.class, String.class);
                if (getAccessToken != null) {
                    getAccessToken.setAccessible(true);
                }
                //反射获取日趋势私有方法
                Method getDailyVisitTrend = BeanUtils.findDeclaredMethod(homeServiceImpl.getClass(), "getDailyVisitTrend", String.class, String.class);
                if (getDailyVisitTrend != null) {
                    getDailyVisitTrend.setAccessible(true);
                }
                String accessToken = (String) redisUtil.get(WeChatConstants.REDIS_PROGRAM_TOKEN_KEY + "_" + channelMerchant.getId());
                //redis中token到期，自动请求新token
                if (StringUtils.isBlank(accessToken)) {
                    String appId = systemConfigService.getValueByKey("routine_appid_" + channelMerchant.getId());
                    String secret = systemConfigService.getValueByKey("routine_appsecret_" + channelMerchant.getId());
                    if (StringUtils.isNotBlank(appId) && StringUtils.isNotBlank(secret)) {
                        JSONObject jsonObject = (JSONObject) getAccessToken.invoke(homeServiceImpl, appId, secret);
                        if (jsonObject == null) {
                            continue;
                        }
                        accessToken = jsonObject.get("access_token").toString();
                        long expires = Long.parseLong(jsonObject.getString("expires_in"));
                        redisUtil.set(WeChatConstants.REDIS_PROGRAM_TOKEN_KEY + "_" + channelMerchant.getId(), accessToken, expires - 100, TimeUnit.SECONDS);
                    } else {
                        log.info("-----------获取小程序访问量失败,商户appid或appsecret不存在,商户id:{} -----------", channelMerchant.getId());
                        continue;
                    }
                }
                //获取上月当天访问量
                Object monthCount = redisUtil.get(StrUtil.format(Constants.APPLET_VISIT_PV, channelMerchant.getId(), LocalDate.now().minusMonths(1).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_NUM))));
                if (Objects.isNull(monthCount)) {
                    Integer dailyVisitTrend = null;
                    //商户创建时间大于查询时间
                    if (channelMerchant.getCreateTime().after(Date.from(LocalDate.now().minusMonths(1).atStartOfDay().atZone(ZoneId.systemDefault()).toInstant()))) {
                        dailyVisitTrend = 0;
                    } else {
                        dailyVisitTrend = (Integer) getDailyVisitTrend.invoke(homeServiceImpl, accessToken, LocalDate.now().minusMonths(1).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_NUM)));
                    }
                    if (Objects.nonNull(dailyVisitTrend)) {
                        month += dailyVisitTrend;
                        redisUtil.set(StrUtil.format(Constants.APPLET_VISIT_PV, channelMerchant.getId(), LocalDate.now().minusMonths(1).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_NUM))), month, 30L, TimeUnit.DAYS);
                    } else {
                        continue;
                    }
                } else {
                    month += (int) monthCount;
                }

                //折线图
                while (startDay.isBefore(nowDay)){
                    //转化为yyyyMMdd形式
                    String date = startDay.format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_NUM));
                    String key = startDay.format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_MONTH_DATE));
                    //商户创建时间大于查询时间,访问量为0
                    if (channelMerchant.getCreateTime().after(Date.from(startDay.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant()))) {
                        flowDataMap.put(key, 0);
                        startDay = startDay.plusDays(1);
                        continue;
                    }
                    //从缓存中读取
                    Object dateCount = redisUtil.get(StrUtil.format(Constants.APPLET_VISIT_PV, channelMerchant.getId(), date));
                    if (Objects.isNull(dateCount)){
                        Integer dailyVisitTrend = (Integer) getDailyVisitTrend.invoke(homeServiceImpl, accessToken, date);
                        if (Objects.nonNull(dailyVisitTrend)){
                            dailyVisitTrend = flowDataMap.get(key) == null ? dailyVisitTrend : (Integer) flowDataMap.get(key) + dailyVisitTrend;
                            flowDataMap.put(key, dailyVisitTrend);
                            redisUtil.set(StrUtil.format(Constants.APPLET_VISIT_PV, channelMerchant.getId(), date), dailyVisitTrend, 30L, TimeUnit.DAYS);
                            continue;
                        }
                    }
                    dateCount = flowDataMap.get(key) == null ? dateCount : (Integer) flowDataMap.get(key) + (Integer) dateCount;
                    flowDataMap.put(key, dateCount);
                    startDay = startDay.plusDays(1);
                }
            } catch (Exception e) {
                e.printStackTrace();
                log.error("-----------获取小程序访问次数异常,商户id:{},msg:{}-----------",channelMerchant.getId(),e.getMessage());
            }
        }
        BigDecimal rateMonth = CrmebUtil.getRateDecimal((int) views.getTodayCount(), month);
        flow.setMonthCount(month)
                .setMonthRate(rateMonth + "%")
                .setLineChart(flowDataMap);

        return flow;
    }

    /**
     * 功能描述: 访问——加购转化率与访问付款转化率
     *
     * @Param: [merIds]
     * @Return: java.util.Map<java.lang.String, com.zbkj.crmeb.store.response.DataLiveSingleResponse>
     * @Author: wangzh
     * @Date: 2022/10/17 18:01
     */
    @Override
    public Map<String, DataLiveSingleResponse> getFlowPurchaseData(List<Integer> merIds) {
        Map<String, DataLiveSingleResponse> responseMap = new HashMap<>();
        //当前时间
        LocalDate now = LocalDate.now();
        dateLimitUtilVo nowLimit = new dateLimitUtilVo(now.format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_START)), now.format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_END)));
        //前一天
        LocalDate yesterday = now.minusDays(1);
        dateLimitUtilVo yesterdayLimit = new dateLimitUtilVo(yesterday.format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_START)), yesterday.format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_END)));
        //前一个月
        LocalDate lastMonthDay = now.minusMonths(1);
        dateLimitUtilVo lastMonthDayLimit = new dateLimitUtilVo(lastMonthDay.format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_START)), lastMonthDay.format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_END)));
        //商品访问总数
        BigDecimal todayVisitNum = getVisitSum(nowLimit, merIds);
        BigDecimal yesterdayVisitNum = getVisitSum(yesterdayLimit, merIds);
        BigDecimal previousVisitNum = getVisitSum(lastMonthDayLimit, merIds);
        //加入购物车总数
        BigDecimal todayAddPurchase = getPurchaseSum(nowLimit, merIds);
        BigDecimal yesterdayAddPurchase = getPurchaseSum(yesterdayLimit, merIds);
        BigDecimal previousAddPurchase = getPurchaseSum(lastMonthDayLimit, merIds);
        //付款订单总数
        BigDecimal todayPayNum = getPaySum(nowLimit, merIds);
        BigDecimal yesterdayPayNum = getPaySum(yesterdayLimit, merIds);
        BigDecimal previousPayNum = getPaySum(lastMonthDayLimit, merIds);

        //访问——加购转化率
        BigDecimal todayVisitPurchase = BigDecimal.ZERO;
        BigDecimal yesterdayVisitPurchase = BigDecimal.ZERO;
        BigDecimal previousVisitPurchase = BigDecimal.ZERO;

        //访问——付款转化率
        BigDecimal todayVisitPay = BigDecimal.ZERO;
        BigDecimal yesterdayVisitPay = BigDecimal.ZERO;
        BigDecimal previousVisitPay = BigDecimal.ZERO;

        if (todayVisitNum.compareTo(BigDecimal.ZERO) != 0) {
            todayVisitPurchase = todayAddPurchase.multiply(BigDecimal.TEN).multiply(BigDecimal.TEN).divide(todayVisitNum, 2, RoundingMode.HALF_UP);
            todayVisitPay = todayPayNum.multiply(BigDecimal.TEN).multiply(BigDecimal.TEN).divide(todayVisitNum, 2, RoundingMode.HALF_UP);
        }

        if (yesterdayVisitNum.compareTo(BigDecimal.ZERO) != 0) {
            yesterdayVisitPurchase = yesterdayAddPurchase.multiply(BigDecimal.TEN).multiply(BigDecimal.TEN).divide(yesterdayVisitNum, 2, RoundingMode.HALF_UP);
            yesterdayVisitPay = yesterdayPayNum.multiply(BigDecimal.TEN).multiply(BigDecimal.TEN).divide(yesterdayVisitNum, 2, RoundingMode.HALF_UP);
        }

        if (previousVisitNum.compareTo(BigDecimal.ZERO) != 0) {
            previousVisitPurchase = previousAddPurchase.multiply(BigDecimal.TEN).multiply(BigDecimal.TEN).divide(previousVisitNum, 2, RoundingMode.HALF_UP);
            previousVisitPay = previousPayNum.multiply(BigDecimal.TEN).multiply(BigDecimal.TEN).divide(previousVisitNum, 2, RoundingMode.HALF_UP);
        }
        //访问——加购转化率
        BigDecimal visitPurchaseDayRate = CrmebUtil.getRateDecimal(todayVisitPurchase, yesterdayVisitPurchase);
        BigDecimal visitPurchaseMonthRate = CrmebUtil.getRateDecimal(todayVisitPurchase, previousVisitPurchase);
        DataLiveSingleResponse visitPurchase = new DataLiveSingleResponse();
        visitPurchase.setTodayCount(todayVisitPurchase + "%")
                .setYesterdayCount(yesterdayVisitPurchase + "%")
                .setMonthCount(previousVisitPurchase + "%")
                .setDayRate(visitPurchaseDayRate + "%")
                .setMonthRate(visitPurchaseMonthRate + "%");
        responseMap.put("visitPurchase", visitPurchase);

        //访问——付款转化率
        BigDecimal visitPayDayRate = CrmebUtil.getRateDecimal(todayVisitPay, yesterdayVisitPay);
        BigDecimal visitPayMonthRate = CrmebUtil.getRateDecimal(todayVisitPay, yesterdayVisitPay);
        DataLiveSingleResponse visitPay = new DataLiveSingleResponse();
        visitPay.setTodayCount(todayVisitPay + "%")
                .setYesterdayCount(yesterdayVisitPay + "%")
                .setMonthCount(previousVisitPay + "%")
                .setDayRate(visitPayDayRate + "%")
                .setMonthRate(visitPayMonthRate + "%");
        responseMap.put("visitPay", visitPay);
        return responseMap;
    }

    /**
     * 功能描述: 获取访客榜
     *
     * @Param: [merIds]
     * @Return: java.util.List<com.zbkj.crmeb.store.response.GoodsBoardResponse>
     * @Author: wangzh
     * @Date: 2022/10/18 11:18
     */
    @Override
    public List<GoodsBoardResponse> getGoodsBoardVisitData(List<Integer> merIds) {
        //本月第一天
        String firstDay = LocalDate.now().with(TemporalAdjusters.firstDayOfMonth()).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_START));
        //本月最后一天
        String endDay = LocalDate.now().with(TemporalAdjusters.lastDayOfMonth()).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_END));
        QueryWrapper<StoreProductActive> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("sum(visitor_number) as visitor_number", "product_id")
                .between("update_time", firstDay, endDay)
                .in(CollectionUtils.isNotEmpty(merIds), "mer_id", merIds)
                .groupBy("product_id")
                .orderByDesc("visitor_number")
                .last("limit 5");
        List<StoreProductActive> goodsList = saleAnalysisService.list(queryWrapper);
        //数据库查询不到数据，说明本月还暂时没有用户行为
        if (CollectionUtils.isEmpty(goodsList)) {
            return null;
        }

        List<GoodsBoardResponse> visitGoods = new ArrayList<>();
        for (int i = 0; i < goodsList.size(); i++) {
            StoreProductDescription descriptionOne = descriptionService.getOne(Wrappers.<StoreProductDescription>lambdaQuery()
                    .eq(StoreProductDescription::getProductId, goodsList.get(i).getProductId())
                    .last("limit 1"));
            StoreProduct productOne = productService.getOne(Wrappers.<StoreProduct>lambdaQuery()
                    .eq(StoreProduct::getId, goodsList.get(i).getProductId())
                    .last("limit 1"));
            GoodsBoardResponse visitGoodsResponse = new GoodsBoardResponse();
            visitGoodsResponse.setSort(i + 1).setImg(descriptionOne.getImage()).setGoodsName(productOne.getStoreName()).setData(goodsList.get(i).getVisitorNumber());
            visitGoods.add(visitGoodsResponse);
        }

        return visitGoods;
    }

    /**
     * 功能描述: 获取销量榜
     *
     * @Param: [merIds]
     * @Return: java.util.List<com.zbkj.crmeb.store.response.GoodsBoardResponse>
     * @Author: wangzh
     * @Date: 2022/10/18 11:29
     */
    @Override
    public List<GoodsBoardResponse> getGoodsBoardSalesVolumeData(List<Integer> merIds) {
        //本月第一天
        String firstDay = LocalDate.now().with(TemporalAdjusters.firstDayOfMonth()).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_START));
        //本月最后一天
        String endDay = LocalDate.now().with(TemporalAdjusters.lastDayOfMonth()).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_END));
        QueryWrapper<StoreProductActive> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("sum(pay_product_number) as pay_product_number", "product_id")
                .between("update_time", firstDay, endDay)
                .in(CollectionUtils.isNotEmpty(merIds), "mer_id", merIds)
                .groupBy("product_id")
                .orderByDesc("pay_product_number")
                .last("limit 5");
        List<StoreProductActive> goodsList = saleAnalysisService.list(queryWrapper);
        //数据库查询不到数据，说明本月还暂时没有用户行为
        if (CollectionUtils.isEmpty(goodsList)) {
            return null;
        }

        List<GoodsBoardResponse> salesVolumeGoods = new ArrayList<>();
        for (int i = 0; i < goodsList.size(); i++) {
            StoreProductDescription descriptionOne = descriptionService.getOne(Wrappers.<StoreProductDescription>lambdaQuery()
                    .eq(StoreProductDescription::getProductId, goodsList.get(i).getProductId())
                    .last("limit 1"));
            StoreProduct productOne = productService.getOne(Wrappers.<StoreProduct>lambdaQuery()
                    .eq(StoreProduct::getId, goodsList.get(i).getProductId())
                    .last("limit 1"));
            GoodsBoardResponse saleGoodsResponse = new GoodsBoardResponse();
            saleGoodsResponse.setSort(i + 1).setImg(descriptionOne.getImage()).setGoodsName(productOne.getStoreName()).setData(goodsList.get(i).getPayProductNumber());
            salesVolumeGoods.add(saleGoodsResponse);
        }

        return salesVolumeGoods;
    }

    /**
     * 功能描述: 支付金额榜
     *
     * @Param: [merIds]
     * @Return: java.util.List<com.zbkj.crmeb.store.response.GoodsBoardResponse>
     * @Author: wangzh
     * @Date: 2022/10/18 11:33
     */
    @Override
    public List<GoodsBoardResponse> getGoodsBoardPayMoneyData(List<Integer> merIds) {
        //本月第一天
        String firstDay = LocalDate.now().with(TemporalAdjusters.firstDayOfMonth()).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_START));
        //本月最后一天
        String endDay = LocalDate.now().with(TemporalAdjusters.lastDayOfMonth()).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_END));
        QueryWrapper<StoreProductActive> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("sum(payment_amount) as payment_amount", "product_id")
                .between("update_time", firstDay, endDay)
                .in(CollectionUtils.isNotEmpty(merIds), "mer_id", merIds)
                .groupBy("product_id")
                .orderByDesc("payment_amount")
                .last("limit 5");
        List<StoreProductActive> goodsList = saleAnalysisService.list(queryWrapper);
        //数据库查询不到数据，说明本月还暂时没有用户行为
        if (CollectionUtils.isEmpty(goodsList)) {
            return null;
        }

        List<GoodsBoardResponse> payMoneyGoods = new ArrayList<>();
        for (int i = 0; i < goodsList.size(); i++) {
            StoreProductDescription descriptionOne = descriptionService.getOne(Wrappers.<StoreProductDescription>lambdaQuery()
                    .eq(StoreProductDescription::getProductId, goodsList.get(i).getProductId())
                    .last("limit 1"));
            StoreProduct productOne = productService.getOne(Wrappers.<StoreProduct>lambdaQuery()
                    .eq(StoreProduct::getId, goodsList.get(i).getProductId())
                    .last("limit 1"));
            GoodsBoardResponse payGoodsResponse = new GoodsBoardResponse();
            payGoodsResponse.setSort(i + 1).setImg(descriptionOne.getImage()).setGoodsName(productOne.getStoreName()).setData(goodsList.get(i).getPaymentAmount());
            payMoneyGoods.add(payGoodsResponse);
        }

        return payMoneyGoods;
    }

    /**
     * @param dateList
     * @Description: 获取实时支付金额
     * @Return: com.zbkj.crmeb.store.response.DataLiveSingleResponse
     * @Author: wangzh
     * @Date: 2022/10/13 15:56
     */
    @Override
    public DataLiveSingleResponse getLivePayMoney(List<String> dateList, List<Integer> merIds) {
        //支付金额
        BigDecimal todayPayMoney = getSumPayMoney(DateUtil.getDateLimit(Constants.SEARCH_DATE_DAY), merIds);
        BigDecimal yesterday = getSumPayMoney(DateUtil.getDateLimit(Constants.SEARCH_DATE_YESTERDAY), merIds);

        Map<Object, Object> moneyMap = new LinkedHashMap<>();
        //零点时刻总支付金额永远等于0
        moneyMap.put(dateList.get(0), BigDecimal.ZERO);
        for (int i = 0; i < dateList.size() - 1; i++) {
            String start = dateList.get(i);
            //LocalDateTime.parse()只可以解析yyyy-MM-ddTHH:mm:ss格式字符，所以将空格替换为T
            String end = LocalDateTime.parse(dateList.get(i + 1).replace(" ", "T")).minus(1, ChronoUnit.SECONDS).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT));
            //获取时间内的金额
            moneyMap.put(dateList.get(i + 1), getSumPayMoney(new dateLimitUtilVo(start, end), merIds));
        }
        //封装对象
        DataLiveSingleResponse payMoney = new DataLiveSingleResponse();
        payMoney.setTodayCount(todayPayMoney)
                .setYesterdayCount(yesterday)
                .setLineChart(moneyMap);
        return payMoney;
    }

    /**
     * @param dateList
     * @param merIds
     * @Description: 获取实时支付订单数
     * @Return: com.zbkj.crmeb.store.response.DataLiveSingleResponse
     * @Author: wangzh
     * @Date: 2022/10/13 16:03
     */
    @Override
    public DataLiveSingleResponse getLivePayOrder(List<String> dateList, List<Integer> merIds) {
        //支付订单数
        Integer todayPayOrder = getSumPayOrder(DateUtil.getDateLimit(Constants.SEARCH_DATE_DAY), merIds);
        Integer yesterdayPayOrder = getSumPayOrder(DateUtil.getDateLimit(Constants.SEARCH_DATE_YESTERDAY), merIds);

        Map<Object, Object> orderMap = new LinkedHashMap<>();
        orderMap.put(dateList.get(0), 0);
        for (int j = 0; j < dateList.size() - 1; j++) {
            String start = dateList.get(j);
            String end = LocalDateTime.parse(dateList.get(j + 1).replace(" ", "T")).minus(1, ChronoUnit.SECONDS).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT));
            orderMap.put(dateList.get(j + 1), getSumPayOrder(new dateLimitUtilVo(start, end), merIds));
        }
        DataLiveSingleResponse payOrder = new DataLiveSingleResponse();
        payOrder.setTodayCount(todayPayOrder)
                .setYesterdayCount(yesterdayPayOrder)
                .setLineChart(orderMap);
        return payOrder;
    }

    /**
     * @param dateList
     * @Description: 获取实时支付人数
     * @Return: com.zbkj.crmeb.store.response.DataLiveSingleResponse
     * @Author: wangzh
     * @Date: 2022/10/13 16:17
     */
    @Override
    public DataLiveSingleResponse getLivePayNum(List<String> dateList, List<Integer> merIds) {
        //支付人数
        Integer todayPayNum = getSumPayNum(DateUtil.getDateLimit(Constants.SEARCH_DATE_DAY), merIds);
        Integer yesterdayPayNum = getSumPayNum(DateUtil.getDateLimit(Constants.SEARCH_DATE_YESTERDAY), merIds);

        //计算每个时段的数据
        Map<Object, Object> payNumMap = new LinkedHashMap<>();
        payNumMap.put(dateList.get(0), 0);
        for (int i = 0; i < dateList.size() - 1; i++) {
            String start = dateList.get(i);
            String end = LocalDateTime.parse(dateList.get(i + 1).replace(" ", "T")).minus(1, ChronoUnit.SECONDS).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT));
            payNumMap.put(dateList.get(i + 1), getSumPayNum(new dateLimitUtilVo(start, end), merIds));
        }
        DataLiveSingleResponse payNum = new DataLiveSingleResponse();
        payNum.setTodayCount(todayPayNum)
                .setYesterdayCount(yesterdayPayNum)
                .setLineChart(payNumMap);
        return payNum;
    }

    /**
     * @param payMoney
     * @param payOrder
     * @Description: 获取实时客单价
     * @Return: com.zbkj.crmeb.store.response.DataLiveSingleResponse
     * @Author: wangzh
     * @Date: 2022/10/13 16:56
     */
    @Override
    public DataLiveSingleResponse getCustomerUnitPrice(DataLiveSingleResponse payMoney, DataLiveSingleResponse payOrder) {
        //订单金额
        BigDecimal todayPayMoney = (BigDecimal) payMoney.getTodayCount();
        BigDecimal yesPayMoney = (BigDecimal) payMoney.getYesterdayCount();
        Map<Object, Object> payMoneyMap = payMoney.getLineChart();
        //订单数量
        BigDecimal todayPayOrder = BigDecimal.valueOf((Integer) payOrder.getTodayCount());
        BigDecimal yesPayOrder = BigDecimal.valueOf((Integer) payOrder.getYesterdayCount());
        Map<Object, Object> payOrderMap = payOrder.getLineChart();

        //客单价
        BigDecimal todayCustomerUnitPrice = BigDecimal.ZERO;
        if (todayPayOrder.compareTo(BigDecimal.ZERO) > 0) {
            todayCustomerUnitPrice = todayPayMoney.divide(todayPayOrder, 2, RoundingMode.HALF_UP);
        }
        BigDecimal yesCustomerUnitPrice = BigDecimal.ZERO;
        if (yesPayOrder.compareTo(BigDecimal.ZERO) > 0) {
            yesCustomerUnitPrice = yesPayMoney.divide(yesPayOrder, 2, RoundingMode.HALF_UP);
        }

        Map<Object, Object> customerUnitPriceMap = new LinkedHashMap<>();
        for (Object key : payOrderMap.keySet()) {
            BigDecimal datePayMoney = (BigDecimal) payMoneyMap.get(key);
            BigDecimal datePayOrder = BigDecimal.valueOf((Integer) payOrderMap.get(key));

            if (datePayOrder.compareTo(BigDecimal.ZERO) == 0) {
                customerUnitPriceMap.put(key, BigDecimal.ZERO);
                continue;
            }

            BigDecimal dateCustomerUnitPrice = datePayMoney.divide(datePayOrder, 2, RoundingMode.HALF_UP);
            customerUnitPriceMap.put(key, dateCustomerUnitPrice);
        }
        DataLiveSingleResponse customerUnitPrice = new DataLiveSingleResponse();
        customerUnitPrice.setTodayCount(todayCustomerUnitPrice)
                .setYesterdayCount(yesCustomerUnitPrice)
                .setLineChart(customerUnitPriceMap);
        return customerUnitPrice;
    }

    /**
     * @param dateList
     * @param merIds
     * @Description: 获取退款金额
     * @Return: com.zbkj.crmeb.store.response.DataLiveSingleResponse
     * @Author: wangzh
     * @Date: 2022/10/14 12:06
     */
    @Override
    public DataLiveSingleResponse getRefundPrice(List<String> dateList, List<Integer> merIds) {

        //退款金额
        BigDecimal todayRefundPrice = getSumRefundPrice(DateUtil.getDateLimit(Constants.SEARCH_DATE_DAY), merIds);
        BigDecimal yesRefundPrice = getSumRefundPrice(DateUtil.getDateLimit(Constants.SEARCH_DATE_YESTERDAY), merIds);

        Map<Object, Object> refundPriceMap = new LinkedHashMap<>();
        refundPriceMap.put(dateList.get(0), BigDecimal.ZERO);
        for (int i = 0; i < dateList.size() - 1; i++) {
            String start = dateList.get(i);
            String end = LocalDateTime.parse(dateList.get(i + 1).replace(" ", "T")).minus(1, ChronoUnit.SECONDS).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT));
            refundPriceMap.put(dateList.get(i + 1), getSumRefundPrice(new dateLimitUtilVo(start, end), merIds));
        }
        DataLiveSingleResponse refundPrice = new DataLiveSingleResponse();
        refundPrice.setTodayCount(todayRefundPrice)
                .setYesterdayCount(yesRefundPrice)
                .setLineChart(refundPriceMap);
        return refundPrice;
    }

    /**
     * @param dateList
     * @param merIds
     * @Description: 实时获取新增会员数
     * @Return: com.zbkj.crmeb.store.response.DataLiveSingleResponse
     * @Author: wangzh
     * @Date: 2022/10/14 14:50
     */
    @Override
    public DataLiveSingleResponse getVIPNum(List<String> dateList, List<Integer> merIds) {
        //新增会员数
        Integer todayVIPNum = getSumVIPNum(DateUtil.getDateLimit(Constants.SEARCH_DATE_DAY), merIds);
        Integer yesVIPNum = getSumVIPNum(DateUtil.getDateLimit(Constants.SEARCH_DATE_YESTERDAY), merIds);

        Map<Object, Object> VIPNumMap = new LinkedHashMap<>();
        VIPNumMap.put(dateList.get(0), 0);
        for (int i = 0; i < dateList.size() - 1; i++) {
            String start = dateList.get(i);
            String end = LocalDateTime.parse(dateList.get(i + 1).replace(" ", "T")).minus(1, ChronoUnit.SECONDS).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT));
            VIPNumMap.put(dateList.get(i + 1), getSumVIPNum(new dateLimitUtilVo(start, end), merIds));
        }
        DataLiveSingleResponse VIPNum = new DataLiveSingleResponse();
        VIPNum.setTodayCount(todayVIPNum)
                .setYesterdayCount(yesVIPNum)
                .setLineChart(VIPNumMap);
        return VIPNum;
    }

    /**
     * @param dateList
     * @param merIds
     * @Description: 获取整体看板中支付金额相关信息
     * @Return: com.zbkj.crmeb.store.response.DataLiveSingleResponse
     * @Author: wangzh
     * @Date: 2022/10/16 15:41
     */
    @Override
    public DataLiveSingleResponse getWholePayMoney(List<String> dateList, List<Integer> merIds, dateLimitUtilVo dateLimit, Integer intervalDay) {

        //支付金额
        BigDecimal present = getSumPayMoney(new dateLimitUtilVo(LocalDate.parse(dateList.get(0)).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_START)), LocalDate.parse(dateList.get(dateList.size() - 1)).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_END))), merIds);
        BigDecimal previous = getSumPayMoney(new dateLimitUtilVo(dateLimit.getStartTime(), dateLimit.getEndTime()), merIds);
        BigDecimal rate = CrmebUtil.getRateDecimal(present, previous);

        Map<Object, Object> payMoneyMap = new LinkedHashMap<>();
        //横坐标第一个节点数据为当天前间隔时间至今天，后续节点数据为前节点至当前节点24点
        payMoneyMap.put(LocalDate.parse(dateList.get(0)).minusDays(intervalDay).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_DATE)) + "~" + dateList.get(0), getSumPayMoney(new dateLimitUtilVo(LocalDate.parse(dateList.get(0)).minusDays(intervalDay).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_START)), LocalDate.parse(dateList.get(0)).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_END))), merIds));
        for (int i = 0; i < dateList.size() - 1; i++) {
            String start = LocalDate.parse(dateList.get(i)).plusDays(1).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_START));
            String end = LocalDate.parse(dateList.get(i + 1)).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_END));
            payMoneyMap.put(LocalDate.parse(dateList.get(i)).plusDays(1) + "~" + dateList.get(i + 1), getSumPayMoney(new dateLimitUtilVo(start, end), merIds));
        }
        payMoneyMap = CrmebUtil.convertKey(payMoneyMap);
        DataLiveSingleResponse wholePayMoney = new DataLiveSingleResponse();
        wholePayMoney.setTodayCount(present)
                .setYesterdayCount(previous)
                .setMonthRate(rate + "%")
                .setLineChart(payMoneyMap);
        return wholePayMoney;
    }

    /**
     * @param dateList
     * @param merIds
     * @param dateLimit
     * @Description: 获取整体看板中支付订单相关信息
     * @Return: com.zbkj.crmeb.store.response.DataLiveSingleResponse
     * @Author: wangzh
     * @Date: 2022/10/16 18:08
     */
    @Override
    public DataLiveSingleResponse getWholePayOrder(List<String> dateList, List<Integer> merIds, dateLimitUtilVo dateLimit, Integer intervalDay) {
        //支付订单
        Integer present = getSumPayOrder(new dateLimitUtilVo(LocalDate.parse(dateList.get(0)).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_START)), LocalDate.parse(dateList.get(dateList.size() - 1)).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_END))), merIds);
        Integer previous = getSumPayOrder(new dateLimitUtilVo(dateLimit.getStartTime(), dateLimit.getEndTime()), merIds);
        BigDecimal rate = CrmebUtil.getRateDecimal(present, previous);

        Map<Object, Object> payOrderMap = new LinkedHashMap<>();
        payOrderMap.put(LocalDate.parse(dateList.get(0)).minusDays(intervalDay).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_DATE)) + "~" + dateList.get(0), getSumPayOrder(new dateLimitUtilVo(LocalDate.parse(dateList.get(0)).minusDays(intervalDay).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_START)), LocalDate.parse(dateList.get(0)).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_END))), merIds));
        for (int i = 0; i < dateList.size() - 1; i++) {
            String start = LocalDate.parse(dateList.get(i)).plusDays(1).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_START));
            String end = LocalDate.parse(dateList.get(i + 1)).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_END));
            payOrderMap.put(LocalDate.parse(dateList.get(i)).plusDays(1) + "~" + dateList.get(i + 1), getSumPayOrder(new dateLimitUtilVo(start, end), merIds));
        }
        payOrderMap = CrmebUtil.convertKey(payOrderMap);
        DataLiveSingleResponse wholePayOrder = new DataLiveSingleResponse();
        wholePayOrder.setTodayCount(present)
                .setYesterdayCount(previous)
                .setMonthRate(rate + "%")
                .setLineChart(payOrderMap);
        return wholePayOrder;
    }

    /**
     * @param dateList
     * @param merIds
     * @param dateLimit
     * @Description: 获取整体看板中支付人数相关信息
     * @Return: com.zbkj.crmeb.store.response.DataLiveSingleResponse
     * @Author: wangzh
     * @Date: 2022/10/16 18:13
     */
    @Override
    public DataLiveSingleResponse getWholePayNum(List<String> dateList, List<Integer> merIds, dateLimitUtilVo dateLimit, Integer intervalDay) {
        //支付人数
        Integer present = getSumPayNum(new dateLimitUtilVo(LocalDate.parse(dateList.get(0)).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_START)), LocalDate.parse(dateList.get(dateList.size() - 1)).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_END))), merIds);
        Integer previous = getSumPayNum(new dateLimitUtilVo(dateLimit.getStartTime(), dateLimit.getEndTime()), merIds);
        BigDecimal rate = CrmebUtil.getRateDecimal(present, previous);

        Map<Object, Object> payNumMap = new LinkedHashMap<>();
        payNumMap.put(LocalDate.parse(dateList.get(0)).minusDays(intervalDay).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_DATE)) + "~" + dateList.get(0), getSumPayNum(new dateLimitUtilVo(LocalDate.parse(dateList.get(0)).minusDays(intervalDay).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_START)), LocalDate.parse(dateList.get(0)).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_END))), merIds));
        for (int i = 0; i < dateList.size() - 1; i++) {
            String start = LocalDate.parse(dateList.get(i)).plusDays(1).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_START));
            String end = LocalDate.parse(dateList.get(i + 1)).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_END));
            payNumMap.put(LocalDate.parse(dateList.get(i)).plusDays(1) + "~" + dateList.get(i + 1), getSumPayNum(new dateLimitUtilVo(start, end), merIds));
        }
        payNumMap = CrmebUtil.convertKey(payNumMap);
        DataLiveSingleResponse wholePayNum = new DataLiveSingleResponse();
        wholePayNum.setTodayCount(present)
                .setYesterdayCount(previous)
                .setMonthRate(rate + "%")
                .setLineChart(payNumMap);
        return wholePayNum;
    }

    /**
     * @param payMoney
     * @param payOrder
     * @Description: 获取整体面板中客单价信息
     * @Return: com.zbkj.crmeb.store.response.DataLiveSingleResponse
     * @Author: wangzh
     * @Date: 2022/10/16 18:40
     */
    @Override
    public DataLiveSingleResponse getWholeCustomerUnitPrice(DataLiveSingleResponse payMoney, DataLiveSingleResponse payOrder) {
        //客单价
        BigDecimal presentCustomerUnitPrice = BigDecimal.ZERO;
        BigDecimal previousCustomerUnitPrice = BigDecimal.ZERO;
        //支付金额
        BigDecimal presentPayMoney = (BigDecimal) payMoney.getTodayCount();
        BigDecimal previousPayMoney = (BigDecimal) payMoney.getYesterdayCount();
        Map<Object, Object> payMoneyMap = payMoney.getLineChart();

        //支付订单数
        BigDecimal presentPayOrder = BigDecimal.valueOf((Integer) payOrder.getTodayCount());
        BigDecimal previousPayOrder = BigDecimal.valueOf((Integer) payOrder.getYesterdayCount());
        Map<Object, Object> payOrderMap = payOrder.getLineChart();
        if (presentPayOrder.compareTo(BigDecimal.ZERO) > 0) {
            presentCustomerUnitPrice = presentPayMoney.divide(presentPayOrder, 2, RoundingMode.HALF_UP);
        }
        if (previousPayOrder.compareTo(BigDecimal.ZERO) > 0) {
            previousCustomerUnitPrice = previousPayMoney.divide(previousPayOrder, 2, RoundingMode.HALF_UP);
        }
        BigDecimal rate = presentCustomerUnitPrice.subtract(previousCustomerUnitPrice);
        if (previousCustomerUnitPrice.compareTo(BigDecimal.ZERO) > 0) {
            rate = rate.divide(previousCustomerUnitPrice, 2, RoundingMode.HALF_UP);
        }

        Map<Object, Object> customerUnitPriceMap = new LinkedHashMap<>();
        for (Object key : payMoneyMap.keySet()) {
            BigDecimal datePayMoney = (BigDecimal) payMoneyMap.get(key);
            BigDecimal datePayOrder = BigDecimal.valueOf((Integer) payOrderMap.get(key));

            if (datePayOrder.compareTo(BigDecimal.ZERO) == 0) {
                customerUnitPriceMap.put(key, BigDecimal.ZERO);
                continue;
            }

            BigDecimal dateCustomerUnitPrice = datePayMoney.divide(datePayOrder, 2, RoundingMode.HALF_UP);
            customerUnitPriceMap.put(key, dateCustomerUnitPrice);
        }
        DataLiveSingleResponse wholeCustomerUnitPrice = new DataLiveSingleResponse();
        wholeCustomerUnitPrice.setTodayCount(presentCustomerUnitPrice)
                .setYesterdayCount(previousCustomerUnitPrice)
                .setMonthRate(rate + "%")
                .setLineChart(customerUnitPriceMap);
        return wholeCustomerUnitPrice;
    }

    /**
     * @param dateList
     * @param merIds
     * @param dateLimit
     * @Description: 获取整体面板中退款金额信息
     * @Return: com.zbkj.crmeb.store.response.DataLiveSingleResponse
     * @Author: wangzh
     * @Date: 2022/10/16 18:46
     */
    @Override
    public DataLiveSingleResponse getWholeRefundPrice(List<String> dateList, List<Integer> merIds, dateLimitUtilVo dateLimit, Integer intervalDay) {
        //退款金额
        BigDecimal present = getSumRefundPrice(new dateLimitUtilVo(LocalDate.parse(dateList.get(0)).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_START)), LocalDate.parse(dateList.get(dateList.size() - 1)).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_END))), merIds);
        BigDecimal previous = getSumRefundPrice(new dateLimitUtilVo(dateLimit.getStartTime(), dateLimit.getEndTime()), merIds);
        BigDecimal rate = CrmebUtil.getRateDecimal(present, previous);

        Map<Object, Object> refundPriceMap = new LinkedHashMap<>();
        refundPriceMap.put(LocalDate.parse(dateList.get(0)).minusDays(intervalDay).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_DATE)) + "~" + dateList.get(0), getSumRefundPrice(new dateLimitUtilVo(LocalDate.parse(dateList.get(0)).minusDays(intervalDay).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_START)), LocalDate.parse(dateList.get(0)).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_END))), merIds));
        for (int i = 0; i < dateList.size() - 1; i++) {
            String start = LocalDate.parse(dateList.get(i)).plusDays(1).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_START));
            String end = LocalDate.parse(dateList.get(i + 1)).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_END));
            refundPriceMap.put(LocalDate.parse(dateList.get(i)).plusDays(1) + "~" + dateList.get(i + 1), getSumRefundPrice(new dateLimitUtilVo(start, end), merIds));
        }
        refundPriceMap = CrmebUtil.convertKey(refundPriceMap);
        DataLiveSingleResponse wholeRefundPrice = new DataLiveSingleResponse();
        wholeRefundPrice.setTodayCount(present)
                .setYesterdayCount(previous)
                .setMonthRate(rate + "%")
                .setLineChart(refundPriceMap);
        return wholeRefundPrice;
    }

    /**
     * @param dateList
     * @param merIds
     * @param dateLimit
     * @Description: 获取整体面板中新增会员信息
     * @Return: com.zbkj.crmeb.store.response.DataLiveSingleResponse
     * @Author: wangzh
     * @Date: 2022/10/16 18:51
     */
    @Override
    public DataLiveSingleResponse getWholeVIPNum(List<String> dateList, List<Integer> merIds, dateLimitUtilVo dateLimit, Integer intervalDay) {
        //会员数
        Integer present = getSumVIPNum(new dateLimitUtilVo(LocalDate.parse(dateList.get(0)).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_START)), LocalDate.parse(dateList.get(dateList.size() - 1)).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_END))), merIds);
        Integer previous = getSumVIPNum(new dateLimitUtilVo(dateLimit.getStartTime(), dateLimit.getEndTime()), merIds);
        BigDecimal rate = CrmebUtil.getRateDecimal(present, previous);

        Map<Object, Object> VIPNumMap = new LinkedHashMap<>();
        VIPNumMap.put(LocalDate.parse(dateList.get(0)).minusDays(intervalDay).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_DATE)) + "~" + dateList.get(0), getSumVIPNum(new dateLimitUtilVo(LocalDate.parse(dateList.get(0)).minusDays(intervalDay).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_START)), LocalDate.parse(dateList.get(0)).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_END))), merIds));
        for (int i = 0; i < dateList.size() - 1; i++) {
            String start = LocalDate.parse(dateList.get(i)).plusDays(1).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_START));
            String end = LocalDate.parse(dateList.get(i + 1)).format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_END));
            VIPNumMap.put(LocalDate.parse(dateList.get(i)).plusDays(1) + "~" + dateList.get(i + 1), getSumVIPNum(new dateLimitUtilVo(start, end), merIds));
        }
        VIPNumMap = CrmebUtil.convertKey(VIPNumMap);
        DataLiveSingleResponse wholeVIPNum = new DataLiveSingleResponse();
        wholeVIPNum.setTodayCount(present)
                .setYesterdayCount(previous)
                .setMonthRate(rate + "%")
                .setLineChart(VIPNumMap);
        return wholeVIPNum;
    }

    /**
     * @param date
     * @Description: 按指定小时间隔获取某天时间集合
     * @Return: java.util.List<java.lang.String>
     * @Author: wangzh
     * @Date: 2022/10/13 10:06
     */
    private List<String> getListDate(Date date, int num) {
        List<String> dates = new ArrayList<>();
        for (int i = 0; i < 25; i += num) {
            dates.add(DateUtil.dateToStr(DateUtil.addHour(date, i), Constants.DATE_FORMAT));
        }
        return dates;
    }

    /**
     * 功能描述: 获取开始时间到结束时间的yyyyMMdd格式(不包含开始时间)
     *
     * @Param: [date]
     * @Return: java.util.List<java.lang.String>
     * @Author: wangzh
     * @Date: 2022/10/17 13:06
     */
    public List<String> getListDateMonth(dateLimitUtilVo date) {
        List<String> dates = new ArrayList<>();

        LocalDate localDate = LocalDate.parse(date.getStartTime()).plusDays(1);
        LocalDate localDate1 = LocalDate.parse(date.getEndTime());
        while (localDate.isBefore(localDate1)) {
            dates.add(localDate.format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_NUM)));
            localDate = localDate.plusDays(1);
        }
        dates.add(localDate1.format(DateTimeFormatter.ofPattern(Constants.DATE_FORMAT_NUM)));
        return dates;
    }

    /**
     * @param dateLimit
     * @param merIds
     * @Description: 获取时间段内退款金额
     * @Return: java.math.BigDecimal
     * @Author: wangzh
     * @Date: 2022/10/13 17:35
     */
    private BigDecimal getSumRefundPrice(dateLimitUtilVo dateLimit, List<Integer> merIds) {
        String merIdList = "(" + merIds.stream().map(String::valueOf).collect(Collectors.joining(",")) + ")";
        QueryWrapper<StoreOrderStatus> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("sum(SUBSTRING_INDEX(SUBSTRING_INDEX(change_message,'用户',-1),'元',1)) as change_message")
                .eq("change_type", Constants.ORDER_LOG_REFUND_PRICE)
                .inSql(merIds.size() != 0, "order_number", "select child_order_number from eb_store_order_info where order_id in (select id from eb_store_order where mer_id in " + merIdList + ")")
                .between("create_time", dateLimit.getStartTime(), dateLimit.getEndTime())
                .last("limit 1");
        StoreOrderStatus storeOrderStatus = storeOrderStatusService.getOne(queryWrapper);
        if (Objects.isNull(storeOrderStatus) || Objects.isNull(storeOrderStatus.getChangeMessage())) {
            return BigDecimal.ZERO;
        }
        return new BigDecimal(storeOrderStatus.getChangeMessage());
    }

    /**
     * @param dateLimit
     * @param merIds
     * @Description: 获取时间范围内的支付金额
     * @Return: java.math.BigDecimal
     * @Author: wangzh
     * @Date: 2022/10/16 13:51
     */
    private BigDecimal getSumPayMoney(dateLimitUtilVo dateLimit, List<Integer> merIds) {
        String merIdList = "(" + merIds.stream().map(String::valueOf).collect(Collectors.joining(",")) + ")";
        QueryWrapper<StoreOrderInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("sum(pay_price+deduction_price) as pay_price")
                .ne("status", 0)
                .ne("status", 5)
                .inSql(CollectionUtils.isNotEmpty(merIds), "order_id", "select id from eb_store_order where mer_id in " + merIdList)
                .between("create_time", dateLimit.getStartTime(), dateLimit.getEndTime())
                .last("limit 1");
        StoreOrderInfo storeOrderInfo = storeOrderInfoService.getOne(queryWrapper);
        if (Objects.isNull(storeOrderInfo) || Objects.isNull(storeOrderInfo.getPayPrice())) {
            return BigDecimal.ZERO;
        }
        return storeOrderInfo.getPayPrice();
    }

    /**
     * @param dateLimit
     * @param merIds
     * @Description: 获取时间范围内的支付订单数
     * @Return: java.lang.Integer
     * @Author: wangzh
     * @Date: 2022/10/16 14:03
     */
    private Integer getSumPayOrder(dateLimitUtilVo dateLimit, List<Integer> merIds) {
        String merIdList = "(" + merIds.stream().map(String::valueOf).collect(Collectors.joining(",")) + ")";
        return storeOrderInfoService.count(Wrappers.<StoreOrderInfo>lambdaQuery()
                .ne(StoreOrderInfo::getStatus, 0)
                .ne(StoreOrderInfo::getStatus, 5)
                .inSql(CollectionUtils.isNotEmpty(merIds), StoreOrderInfo::getOrderId, "select id from eb_store_order where mer_id in " + merIdList)
                .between(StoreOrderInfo::getCreateTime, dateLimit.getStartTime(), dateLimit.getEndTime()));
    }

    /**
     * @param dateLimit
     * @param merIds
     * @Description: 获取时间范围内支付人数
     * @Return: java.lang.Integer
     * @Author: wangzh
     * @Date: 2022/10/16 14:13
     */
    private Integer getSumPayNum(dateLimitUtilVo dateLimit, List<Integer> merIds) {
        LambdaQueryWrapper<StoreOrder> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.ne(StoreOrder::getStatus, 0)
                .ne(StoreOrder::getStatus, 5)
                .in(CollectionUtils.isNotEmpty(merIds), StoreOrder::getMerId, merIds)
                .between(StoreOrder::getCreateTime, dateLimit.getStartTime(), dateLimit.getEndTime())
                .groupBy(StoreOrder::getUid);
        return storeOrderDao.getPayOrderUserNum(lambdaQueryWrapper);
    }

    /**
     * @param dateLimit
     * @param merIds
     * @Description: 获取时间范围内的新增会员数
     * @Return: java.lang.Integer
     * @Author: wangzh
     * @Date: 2022/10/16 14:25
     */
    private Integer getSumVIPNum(dateLimitUtilVo dateLimit, List<Integer> merIds) {
        return userService.count(Wrappers.<User>lambdaQuery()
                .in(CollectionUtils.isNotEmpty(merIds), User::getMerId, merIds)
                .between(User::getCreateTime, dateLimit.getStartTime(), dateLimit.getEndTime()));
    }

    /**
     * 功能描述: 获取时间范围内访客数量
     *
     * @return
     * @Param: [dateLimit, merIds]
     * @Return: java.lang.Integer
     * @Author: wangzh
     * @Date: 2022/10/17 16:55
     */
    private BigDecimal getVisitSum(dateLimitUtilVo dateLimit, List<Integer> merIds) {
        QueryWrapper<StoreProductActive> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("sum(visitor_number) as visitor_number")
                .between(dateLimit != null, "update_time", dateLimit.getStartTime(), dateLimit.getEndTime())
                .in("mer_id", merIds)
                .last("limit 1");
        StoreProductActive one = saleAnalysisService.getOne(queryWrapper);
        if (Objects.isNull(one)) {
            return BigDecimal.ZERO;
        }
        return new BigDecimal(one.getVisitorNumber());
    }

    /**
     * 功能描述: 获取时间范围内加购数量
     *
     * @Param: [dateLimit, merIds]
     * @Return: java.lang.Integer
     * @Author: wangzh
     * @Date: 2022/10/17 17:36
     */
    private BigDecimal getPurchaseSum(dateLimitUtilVo dateLimit, List<Integer> merIds) {
        QueryWrapper<StoreProductActive> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("sum(add_purchase_number) as add_purchase_number")
                .between(dateLimit != null, "update_time", dateLimit.getStartTime(), dateLimit.getEndTime())
                .in("mer_id", merIds)
                .last("limit 1");
        StoreProductActive one = saleAnalysisService.getOne(queryWrapper);
        if (Objects.isNull(one)) {
            return BigDecimal.ZERO;
        }
        return new BigDecimal(one.getAddPurchaseNumber());
    }

    /**
     * 功能描述: 获取时间范围内支付总数
     *
     * @Param: [dateLimit, merIds]
     * @Return: java.lang.Integer
     * @Author: wangzh
     * @Date: 2022/10/17 17:44
     */
    private BigDecimal getPaySum(dateLimitUtilVo dateLimit, List<Integer> merIds) {
        QueryWrapper<StoreProductActive> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("sum(pay_product_number) as pay_product_number")
                .between(dateLimit != null, "update_time", dateLimit.getStartTime(), dateLimit.getEndTime())
                .in("mer_id", merIds)
                .last("limit 1");
        StoreProductActive one = saleAnalysisService.getOne(queryWrapper);
        if (Objects.isNull(one)) {
            return BigDecimal.ZERO;
        }
        return new BigDecimal(one.getPayProductNumber());
    }
}
